using AYellowpaper.SerializedCollections;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using ZSW.Framework;

namespace ZSW.Framework.Signal
{
    public class ZSWF_SignalSystem : ZSWF_Singleton<ZSWF_SignalSystem>
    {
        [SerializedDictionary, SerializeField]
        private SerializedDictionary<string, int> m_signalEvents;

        private Dictionary<string, ISignalData> m_signalDictionary;
        public ZSWF_SignalSystem()
        {
            m_signalEvents = new SerializedDictionary<string, int>();
            m_signalDictionary = new Dictionary<string, ISignalData>();
        }

        // 注册信号事件（多线程未测试过）
        public void Register<T>(string key, UnityAction<T> action, int priority = 0)
        {
            if (m_signalDictionary.TryGetValue(key, out var previousAction))
            {
                if (previousAction is SignalData<T> messageData)
                {
                    messageData.Add(action, priority);
                    m_signalEvents[key]++;
                }
                else
                {
                    LogError($"Signal key {key} event register failed, {previousAction} is not SignalData<T> messageData");
                }
            }
            else
            {
                m_signalDictionary.Add(key, new SignalData<T>(action, priority));
                m_signalEvents.Add(key, 1);
            }
            Log($"Signal key {key} event register successfully");
        }

        public void Register(string key, UnityAction action, int priority = 0)
        {
            if (m_signalDictionary.TryGetValue(key, out var previousAction))
            {
                if (previousAction is SignalData messageData)
                {
                    messageData.Add(action, priority);
                    m_signalEvents[key]++;
                }
                else
                {
                    LogError($"Signal key {key} event register failed, {previousAction} is not SignalData messageData");
                }
            }
            else
            {
                m_signalDictionary.Add(key, new SignalData(action, priority));
                m_signalEvents.Add(key, 1);
            }
            Log($"Signal key {key} event register successfully");
        }

        // 发送信号
        public void Send<T>(string key, T value)
        {
            if (m_signalDictionary.TryGetValue(key, out var action))
            {
                (action as SignalData<T>)?.Invoke(value);
                Log($"Signal key {key} recevive signal : {value}");
            }
        }

        public void Send(string key)
        {
            if (m_signalDictionary.TryGetValue(key, out var action))
            {
                (action as SignalData)?.Invoke();
                Log($"Signal key {key} recevive signal");
            }
        }

        public void Remove<T>(string key, UnityAction<T> action)
        {
            if (m_signalDictionary.TryGetValue(key, out var previousAction))
            {
                if (previousAction is SignalData<T> messageData)
                {
                    messageData.Remove(action);
                }
            }
            Log($"Signal key {key} event remove successfully");
        }

        public void Remove(string key, UnityAction action)
        {
            if (m_signalDictionary.TryGetValue(key, out var previousAction))
            {
                if (previousAction is SignalData messageData)
                {
                    messageData.Remove(action);
                }
            }
            Log($"Signal key {key} event remove successfully");
        }
    }

    public static class Signal
    {
        public static void Register<T>(string key, UnityAction<T> action, int priority = 0)
        {
            ZSWF_SignalSystem.Instance.Register(key, action, priority);
        }

        public static void Register(string key, UnityAction action, int priority = 0)
        {
            ZSWF_SignalSystem.Instance.Register(key, action, priority);
        }

        public static void Send<T>(string key, T value)
        {
            ZSWF_SignalSystem.Instance.Send(key, value);
        }

        public static void Send(string key)
        {
            ZSWF_SignalSystem.Instance.Send(key);
        }

        public static void Remove<T>(string key, UnityAction<T> action)
        {
            ZSWF_SignalSystem.Instance.Remove(key, action);
        }

        public static void Remove(string key, UnityAction action)
        {
            ZSWF_SignalSystem.Instance.Remove(key, action);
        }
    }
}
